// Copyright (c) 2025 coze-dev Authors
// SPDX-License-Identifier: Apache-2.0

package scheduledtask

import (
	"context"
	"time"

	"github.com/coze-dev/coze-loop/backend/modules/llm/pkg/goroutineutil"
	"github.com/coze-dev/coze-loop/backend/pkg/logs"
)

type ScheduledTask interface {
	Run() error
	RunOnce(ctx context.Context) error
	Stop() error
}

type BaseScheduledTask struct {
	ScheduledTask
	name         string
	timeInterval time.Duration
	stopChan     chan struct{}
	runAtStartup bool
}

func NewBaseScheduledTask(name string, timeInterval time.Duration, runAtStartup bool) *BaseScheduledTask {
	return &BaseScheduledTask{
		name:         name,
		timeInterval: timeInterval,
		stopChan:     make(chan struct{}),
		runAtStartup: runAtStartup,
	}
}

func (b *BaseScheduledTask) Run() error {
	ticker := time.NewTicker(b.timeInterval)
	if b.runAtStartup {
		if err := b.ScheduledTask.RunOnce(context.Background()); err != nil {
			return err
		}
	}
	goroutineutil.GoWithDefaultRecovery(context.Background(), func() {
		defer ticker.Stop()
		for {
			select {
			case <-ticker.C:
				ctx := context.Background()
				startTime := time.Now()
				if err := b.ScheduledTask.RunOnce(ctx); err != nil {
					logs.CtxError(ctx, "ScheduledTask [%s] run error: %v, cost: %v", b.name, err, time.Since(startTime))
				} else {
					logs.CtxInfo(ctx, "ScheduledTask [%s] run success, cost: %v", b.name, time.Since(startTime))
				}
			case <-b.stopChan:
				return
			}
		}
	})
	return nil
}

func (b *BaseScheduledTask) RunOnce(ctx context.Context) error {
	panic("implement me")
}

func (b *BaseScheduledTask) Stop() error {
	close(b.stopChan)
	return nil
}
